package controller

import (
	"encoding/json"
	"sync/atomic"

	"github.com/astaxie/beego/validation"
	"github.com/sirupsen/logrus"

	"cvevulner/cve-ddd/app"
)

const allowConcurrency = 1

var concurrency atomic.Int32

func NewCveController(
	c app.ColdPatchService,
	b app.BulletinService,
	h app.RefactorHotPatchService,
	hl *logrus.Entry,
	bl *logrus.Entry,
) *CveController {
	return &CveController{
		HotPatchBulletinLog: hl,
		BulletinLog:         bl,
		ColdPatchService:    c,
		BulletinService:     b,
		HotPatchService:     h,
	}
}

type CveController struct {
	BaseController

	HotPatchBulletinLog *logrus.Entry
	BulletinLog         *logrus.Entry
	ColdPatchService    app.ColdPatchService
	BulletinService     app.BulletinService
	HotPatchService     app.RefactorHotPatchService
}

func (c *CveController) CollectCveData() {
	var request CollectRequest
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &request); err != nil {
		c.fail(err.Error())

		return
	}

	valid := validation.Validation{}
	b, err := valid.Valid(&request)
	if err != nil || !b {
		c.fail("param error")

		return
	}

	c.ColdPatchService.CollectCveData(request)

	c.success(nil)
}

func (c *CveController) Generate() {
	var request GenerateRequest
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &request); err != nil {
		c.fail(err.Error())

		return
	}

	valid := validation.Validation{}
	b, err := valid.Valid(&request)
	if err != nil || !b {
		c.fail("param error")

		return
	}

	go func() {
		defer func() {
			if r := recover(); r != nil {
				c.BulletinLog.Errorf("handle collect panic: %v", r)
			}
		}()

		concurrency.Add(1)
		defer concurrency.Add(-1)

		// 公告接口不允许并发访问
		if concurrency.Load() > allowConcurrency {
			c.BulletinLog.Errorf("job is running")

			return
		}

		uploadDir, err1 := c.BulletinService.GenerateBulletins(request)
		if err1 != nil {
			c.BulletinLog.Errorf("generate security bulletins failed: %s", err1.Error())
		} else {
			err1 = c.HotPatchService.GenerateBulletins(uploadDir, request.Date)
			if err1 != nil {
				c.HotPatchBulletinLog.Errorf("generate hot patch security bulletins failed: %s", err1.Error())
			}
		}
	}()

	c.success(nil)
}

// Move notice file from upload dir to release dir
func (c *CveController) Move() {
	if err := c.BulletinService.Move(); err != nil {
		c.fail(err.Error())
	} else {
		c.success(nil)
	}
}
